
#include "ls_common.h"
#include "bflb_gpio.h"
#include "lwip/tcpip.h"
#include "lwip/apps/sntp.h"

#include "ls_wifi_sta.h"
#include "ls_little_fs.h"
#include "ls_config_file.h"
#include "ls_p2p_client.h"
#include "ls_struct_flash.h"
#include "ls_dc357.h"
#include "ls_audio.h"
#include "ls_dm.h"
#include "ls_rtc.h"
#include "ls_http_post.h"
#include "mem.h"

#define DBG_TAG "MAIN"
#include "ls_trace_common.h"

extern Ring_Buffer_Type shell_rb;
extern void shell_release_sem(void);

void board_jtag_gpio_init()
{
    struct bflb_device_s *gpio;

    gpio = bflb_device_get_by_name("gpio");
    bflb_gpio_init(gpio, GPIO_PIN_18, GPIO_FUNC_JTAG | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_0);
    bflb_gpio_init(gpio, GPIO_PIN_19, GPIO_FUNC_JTAG | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_0);
    bflb_gpio_init(gpio, GPIO_PIN_16, GPIO_FUNC_JTAG | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_0);
    bflb_gpio_init(gpio, GPIO_PIN_17, GPIO_FUNC_JTAG | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_0);
    LS_TRACE_DEBUG("SET GPIO 10 11 12 13 JTAG");
}

extern void shell_init_with_task(struct bflb_device_s *shell);

static uint8_t net_is_ok = 0;
sem_t p2p_info_sem;

/// @brief
/// @param s
static void __wifi_conennct(WIFI_STATUS s)
{
    if (s == WIFI_INIT_DONE) {
        char ssid[64];
        char passwd[64];
        if (ls_config_get_wifi(ssid, passwd) == 0) {
            ls_wifi_sta_connect(ssid,passwd);
        }

    } else if (s == WIFI_CONENCT_OK) {
        LS_TRACE_DEBUG("wifi_coencnt_success!");
        ls_audio_play_internal(E_NET_CONENCT_OK);
        sem_post(&p2p_info_sem);
    }
}

/// @brief
/// @param date
/// @param len
static void __ls_audio_data_cb(const char *date, uint32_t len)
{
    // const uint32_t *data32 =(const uint32_t *)date;

    // ls_p2p_client_send_data_udp(P2P_CHANNEL_AUDIO,data32,len);

    // LS_TRACE_DEBUG("date:%p len:%d!",date,len);
    // int j= 0;
    // for(uint16_t i = 0;i < (len/4);i++)
    // {
    //     printf("0x%04x ,",data32[i]);
    //     j++;
    //     if((j%16 == 0))
    //         printf("\r\n");
    // }
    // printf("\r\n");
}

#define P2P_TEST_DEVICE_ID "SOLARA-000000-JEEMM"

/// @brief
/// @param channel
/// @param data
/// @param datalen

static void __ls_dc357_data_cb(uint8_t channel, const char *data, uint32_t datalen)
{
    // 格式化时间
    static char data_string[24] = { 0 };
    //LS_TRACE_DEBUG("readsize:%d", datalen);

    switch (channel) {
        case CUSTOM_CHANNEL_IMG:
        {
            if (net_is_ok == 0)
            break;
            
            if (data == NULL) {
                // 获取当前时间
                struct timeval tp;
                ls_gettimeofday(&tp);
                // 将时间转换为本地时间
                struct tm *local = localtime(&tp.tv_sec);
                local->tm_mday += 1;
                memset(data_string, 0, sizeof(data_string));
                strftime(data_string, sizeof(data_string), "%Y-%m-%d %H:%M:%S", local);
                LS_TRACE_DEBUG("%s", data_string);
                ls_http_post_img_start(P2P_TEST_DEVICE_ID);
            } else {
                ls_http_post_img_data(data, datalen);
                if (datalen < 1024) {
                    ls_http_post_img_end();
                    ls_http_post_alarm_msg(P2P_TEST_DEVICE_ID, data_string);
                }
            }
        }
        break;
        case CUSTOM_CHANNEL_WIFI:
        {
            char *ssid;
            char *passwd;
            char *pdata = data;
            ssid = pdata;
            passwd = pdata + strlen(pdata)+1;
            ls_wifi_sta_connect(ssid,passwd);
        } 
        break;
        default:
        {
            ls_p2p_client_send_data_udp(channel, data, datalen);
        } 
        break;
    }
}

/// @brief
/// @param channel
/// @param data
/// @param datalen
static void __ls_p2p_data_cb(P2P_CHANNEL_E channel, const char *data, uint32_t datalen)
{
    ls_dc357_p2p_send_cmd(channel, data, datalen);
    // LS_TRACE_DEBUG("readsize:%d", datalen);
}

/// @brief
/// @param status
static void __ls_p2p_connect_status(uint8_t status)
{
    if (status) {
        LS_TRACE_DEBUG("p2p connect");
        ls_dc357_p2p_client_conenct();
    } else {
        LS_TRACE_DEBUG("p2p close");
        ls_dc357_p2p_client_close();
    }
}

// extern int settimeofday(const struct timeval *tp, const struct timezone *tzp);
/// @brief
static void __ls_sntp_time_cb(uint32_t time)
{
    LS_TRACE_DEBUG("time:%u:", time);
    struct timeval tv;
    tv.tv_sec = time - 57600;
    ls_settimeofday(&tv);
}

/// @brief
/// @param xTimer /
static void __ls_sntp_timer_sync_check(TimerHandle_t xTimer)
{
    sntp_stop();
    // 获取当前时间
    struct timeval tp;
    ls_gettimeofday(&tp);
    if (tp.tv_sec < 100) {
        LS_TRACE_DEBUG("sntp sync timer start!");
        sntp_init();
    } else {
        struct tm *local = localtime(&tp.tv_sec);
        static uint8_t day = 0;
        if (local->tm_mday != day) {
            xTimerChangePeriod(xTimer, 30000, 0);
            sntp_init();
            day = local->tm_mday;
        }
    }
}

/// @brief
void __ls_p2p_client_init()
{
    sem_wait(&p2p_info_sem);

    //
    sntp_setservername(0, "cn.pool.ntp.org");
    sntp_setservername(1, "ntp.org.cn");
    sntp_setservername(2, "ntp1.aliyun.com");
    sntp_set_time_update_callback(__ls_sntp_time_cb);
    sntp_init();
    //
    TimerHandle_t timeId = xTimerCreate("ntp_check", 3000, pdTRUE, (void *)2, __ls_sntp_timer_sync_check);
    xTimerStart(timeId, 3000);

    ls_dc357_p2p_client_close();
    ls_dc357_send_wifi_status(1);
    //p2p
    ls_p2p_client_init(__ls_p2p_data_cb, __ls_p2p_connect_status);
    ls_dc357_send_wifi_status(2);
    //
    ls_dm_init();
    net_is_ok = 1;
    vTaskDelete(NULL);
}

void BriefPrint()
{
    char szTmp[128];
    printf("\r\n");
    printf("\033[1;35m######################\r\n");
    printf("\033[1;35m%21s\033[0;39m\r\n", LS_FORMAT_VERSION_STRING(szTmp));
    printf("\033[1;35m%21s\033[0;39m\r\n", LS_FORMAT_VER_TIME_STRING());
    printf("\033[1;35m##########  ##########\r\n");
    printf("\033[1;35m########      ########\r\n");
    printf("\033[1;35m####              ####\r\n");
    printf("\033[1;35m%13s\033[0;39m\r\n", LS_SERIES_NAME);
#ifdef LS_COMPILE_REALSE
    printf("\033[1;35m####    REALSE    ####\r\n");
#else
    printf("\033[1;35m####    DEBUG     ####\r\n");
#endif
    printf("\033[1;35m########      ########\r\n");
    printf("\033[1;35m##########  ##########\r\n");
    printf("\033[1;35m######################\033[m\r\n");
    printf("\033[1;35m#Git:%s\033[m\r\n", LS_FORMAT_GIT_HARD_STRING());
}

int main(void)
{
    board_init();
    board_jtag_gpio_init();

    //
    BriefPrint();

    //shell
    struct bflb_device_s *uart0 = bflb_device_get_by_name("uart0");
    shell_init_with_task(uart0);

    //
    ls_struct_falsh_init();

    //fs
    ls_little_fs_init();

    //配置文件
    ls_config_file_init();

    //lwip
    tcpip_init(NULL, NULL);

    //wifi
    ls_wifi_sta_init(__wifi_conennct);

    //audio
    ls_audio_init(__ls_audio_data_cb);

    //
    ls_dc357_init(__ls_dc357_data_cb);

    //
    // void *test=ls_malloc(3072*1024);
    // LS_TRACE_DEBUG("test:%p",test);

    // struct meminfo info;
    // bflb_mem_usage(KMEM_HEAP,&info);
    // LS_TRACE_DEBUG("info.total_size:%d",info.total_size);
    // LS_TRACE_DEBUG("info.free_node:%d",info.free_node);
    // LS_TRACE_DEBUG("info.free_node:%d",info.free_size);
    // LS_TRACE_DEBUG("info.used_node:%d",info.used_node);
    // LS_TRACE_DEBUG("info.used_size:%d",info.used_size);
    // LS_TRACE_DEBUG("info.max_free_size:%d",info.max_free_size);

    // //
    // void *test1=ls_malloc(1024*1024);
    // LS_TRACE_DEBUG("test:%p",test1);

    // bflb_mem_usage(KMEM_HEAP,&info);
    // LS_TRACE_DEBUG("1info.total_size:%d",info.total_size);
    // LS_TRACE_DEBUG("1info.free_node:%d",info.free_node);
    // LS_TRACE_DEBUG("1info.free_node:%d",info.free_size);
    // LS_TRACE_DEBUG("1info.used_node:%d",info.used_node);
    // LS_TRACE_DEBUG("1info.used_size:%d",info.used_size);
    // LS_TRACE_DEBUG("1info.max_free_size:%d",info.max_free_size);
    sem_init(&p2p_info_sem, 0, 0);

    pthread_t p2p_pid = 0;
    pthread_attr_t attr;
    uint32_t stacksize = 0x8000;
    pthread_attr_init(&attr); /*初始化线程属性*/
    pthread_attr_setstacksize(&attr, stacksize);
    pthread_create(&p2p_pid, &attr, __ls_p2p_client_init, NULL);
    pthread_attr_destroy(&attr);
    pthread_detach(p2p_pid);

    vTaskStartScheduler();

    while (1) {
        sleep(1);
    }
}
